import requests
import time
import json
import pandas as pd
import os
from datetime import datetime

# 配置
# 接口来源：https://docs.cvte.com/docs/oa/oa-1fvre8rejo4to
GET_OPERATION_LIST_URL = 'https://csb-api.gz.cvte.cn/wfp-api/v1/wfp/api/wf/ext/getOperationList'
APPROVE_PROCESS_URL = 'https://csb-api.gz.cvte.cn/wfp-api/v1/wfp/api/wf/ext/approveProcess'
DRAFTER_ACCOUNT = 'dscm_admin'   # 查询任务ID时使用的账号

# 文件名
INPUT_FILE = 'data.xlsx'  # 输入的Excel文件
PROCESSED_FILE = 'processed.txt'  # 已处理的ID记录文件
ERROR_FILE = 'errorList.txt'      # 处理失败的ID记录文件
LOG_FILE = 'process.log'          # 日志文件


def log_message(message):
    """
    记录日志
    """
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] {message}"
    print(log_entry)
    
    with open(LOG_FILE, 'a', encoding='utf-8') as f:
        f.write(log_entry + '\n')


def get_task_id(form_instance_id, handler_account=DRAFTER_ACCOUNT):
    """
    查询单据的任务ID
    """
    headers = {
        'Content-Type': 'application/json',
        'Cookie': 'BIGipServerpool_yp_ingress_nginx_dev_it=2620265738.26745.0000'
    }
    
    data = {
        "formInstanceId": form_instance_id,
        "handlerAccount": handler_account
    }
    
    try:
        response = requests.post(GET_OPERATION_LIST_URL, headers=headers, data=json.dumps(data), timeout=30)
        response.raise_for_status()
        result = response.json()
        
        if result.get('status') == '0' and result.get('data'):
            # 获取第一个任务的ID
            task_data = result['data'][0]
            task_id = task_data.get('taskId')
            activity_type = task_data.get('activityType')
            
            # 查找"废弃"操作对应的operationType
            operation_type = None
            if 'operations' in task_data:
                for operation in task_data['operations']:
                    if operation.get('operationName') == '废弃':
                        operation_type = operation.get('operationType')
                        break
            
            return task_id, activity_type, operation_type
        else:
            error_msg = f"获取任务ID失败，单据ID: {form_instance_id}, 响应: {result}"
            log_message(error_msg)
            return None, None, None
    except Exception as e:
        error_msg = f"查询任务ID时发生异常，单据ID: {form_instance_id}, 错误: {e}"
        log_message(error_msg)
        return None, None, None


def abandon_document(form_instance_id, task_id, activity_type, operation_type, handler_account=DRAFTER_ACCOUNT):
    """
    作废单据
    """
    headers = {
        'Content-Type': 'application/json'
    }
    
    data = {
        "formInstanceId": form_instance_id,
        "handlerAccount": handler_account,
        "processParam": {
            "activityType": activity_type,
            "operationType": operation_type,
            "taskId": task_id
        }
    }
    
    try:
        response = requests.post(APPROVE_PROCESS_URL, headers=headers, data=json.dumps(data), timeout=30)
        response.raise_for_status()
        result = response.json()
        
        if result.get('status') == '0':
            return True, "作废成功"
        else:
            error_msg = f"作废单据失败，单据ID: {form_instance_id}, 响应: {result}"
            log_message(error_msg)
            return False, error_msg
    except Exception as e:
        error_msg = f"作废单据时发生异常，单据ID: {form_instance_id}, 错误: {e}"
        log_message(error_msg)
        return False, error_msg


def read_processed_ids():
    """
    读取已处理的ID列表
    """
    if not os.path.exists(PROCESSED_FILE):
        return set()
    
    try:
        with open(PROCESSED_FILE, 'r', encoding='utf-8') as f:
            return set(line.strip() for line in f if line.strip())
    except Exception as e:
        log_message(f"读取已处理ID文件失败: {e}")
        return set()


def save_processed_id(form_instance_id):
    """
    保存已处理的ID
    """
    try:
        with open(PROCESSED_FILE, 'a', encoding='utf-8') as f:
            f.write(form_instance_id + '\n')
    except Exception as e:
        log_message(f"保存已处理ID失败: {form_instance_id}, 错误: {e}")


def save_error_id(form_instance_id, error_message=""):
    """
    保存处理失败的ID
    """
    try:
        with open(ERROR_FILE, 'a', encoding='utf-8') as f:
            if error_message:
                f.write(f"{form_instance_id} - {error_message}\n")
            else:
                f.write(form_instance_id + '\n')
    except Exception as e:
        log_message(f"保存错误ID失败: {form_instance_id}, 错误: {e}")


def save_excel_file(df, suffix=""):
    """
    保存Excel文件
    """
    output_file = f"processed.xlsx"
    try:
        df.to_excel(output_file, index=False)
        log_message(f"处理结果已保存到: {output_file}")
        return output_file
    except Exception as e:
        log_message(f"保存Excel文件失败: {e}")
        return None


def process_excel_documents():
    """
    主处理函数 - 处理Excel文件
    """
    if not os.path.exists(INPUT_FILE):
        log_message(f"输入文件 {INPUT_FILE} 不存在")
        return
    
    # 读取已处理的ID
    processed_ids = read_processed_ids()
    log_message(f"已处理的单据数量: {len(processed_ids)}")
    
    # 读取Excel文件
    try:
        df = pd.read_excel(INPUT_FILE)
        log_message(f"Excel文件读取成功，共有 {len(df)} 行数据")
    except Exception as e:
        log_message(f"读取Excel文件失败: {e}")
        return
    
    # 检查是否存在"处理结果"列，如果不存在则添加
    if '处理结果' not in df.columns:
        df['处理结果'] = ''
        log_message("添加了'处理结果'列")
    else:
        log_message("'处理结果'列已存在")
    
    # 获取单据ID列名（假设为"单据ID"或类似名称）
    document_id_column = None
    for col in df.columns:
        if '单据ID' in col or '单据id' in col or 'document' in col.lower():
            document_id_column = col
            break
    
    if not document_id_column:
        log_message("未找到单据ID列，请确保Excel文件中有包含'单据ID'的列")
        return
    
    log_message(f"使用'{document_id_column}'列作为单据ID列")
    
    # 立即保存一次带有"处理结果"列的文件
    save_excel_file(df, "initial")
    
    # 处理每一行数据
    total_count = len(df)
    processed_count = 0
    success_count = 0
    error_count = 0
    
    for index, row in df.iterrows():
        form_instance_id = str(row[document_id_column]).strip()
        
        # 跳过空的单据ID
        if not form_instance_id or form_instance_id == 'nan':
            log_message(f"跳过第 {index+1} 行，单据ID为空")
            # 更新处理结果列
            if pd.isna(df.at[index, '处理结果']) or df.at[index, '处理结果'] == '':
                df.at[index, '处理结果'] = '跳过（单据ID为空）'
                # 立即保存更新
                save_excel_file(df, f"updated_row_{index}")
            continue
        
        # 跳过已处理的ID
        if form_instance_id in processed_ids:
            log_message(f"跳过已处理的单据: {form_instance_id}")
            # 更新处理结果列
            if pd.isna(df.at[index, '处理结果']) or df.at[index, '处理结果'] == '':
                df.at[index, '处理结果'] = '已处理'
                # 立即保存更新
                save_excel_file(df, f"updated_row_{index}")
            continue
        
        processed_count += 1
        log_message(f"正在处理第 {index+1}/{total_count} 个单据: {form_instance_id}")
        
        # 获取处理人账号（如果存在）
        handler_account = DRAFTER_ACCOUNT
        if '处理人账号' in df.columns:
            handler_account_val = str(row['处理人账号']).strip()
            if handler_account_val and handler_account_val != 'nan':
                handler_account = handler_account_val
        
        # 查询任务ID
        task_id, activity_type, operation_type = get_task_id(form_instance_id, handler_account)
        if not task_id:
            error_msg = "获取任务ID失败"
            log_message(f"{error_msg}: {form_instance_id}")
            save_error_id(form_instance_id, error_msg)
            df.at[index, '处理结果'] = f'失败: {error_msg}'
            error_count += 1
            # 保存更新后的Excel文件
            save_excel_file(df, f"updated_row_{index}")
            continue
        
        # 如果没有找到废弃操作类型，使用默认值
        if not operation_type:
            operation_type = "admin_abandon"
            log_message(f"未找到废弃操作类型，使用默认值: {operation_type}")
        
        # 作废单据
        success, message = abandon_document(form_instance_id, task_id, activity_type, operation_type, handler_account)
        if success:
            log_message(f"作废成功: {form_instance_id}")
            save_processed_id(form_instance_id)
            df.at[index, '处理结果'] = '成功'
            success_count += 1
        else:
            log_message(f"作废失败: {form_instance_id}")
            save_error_id(form_instance_id, message)
            df.at[index, '处理结果'] = f'失败: {message}'
            error_count += 1
        
        # 立即保存更新后的Excel文件
        save_excel_file(df, f"updated_row_{index}")
        
        # 每秒处理一个
        if index < total_count - 1:  # 最后一个不需要等待
            time.sleep(1)
    
    # 保存最终的Excel文件
    final_file = save_excel_file(df, "final")
    
    log_message(f"处理完成。总计: {processed_count}, 成功: {success_count}, 失败: {error_count}")
    if final_file:
        log_message(f"最终结果文件: {final_file}")


if __name__ == "__main__":
    log_message("程序开始执行")
    try:
        process_excel_documents()
    except KeyboardInterrupt:
        log_message("程序被用户中断")
    except Exception as e:
        log_message(f"程序执行出错: {e}")
    finally:
        log_message("程序执行结束")